#pragma once

#include <iostream>
#include <string>
#include <functional>
#include <cstdio>
#include <cassert>
using namespace std;

const string operators = "+-*/%";
const char* save_file = "./log.txt";

class CalculateTask {
private:
    using func_t = function<int(int, int, char)>;

private:
    int _num1;
    int _num2;
    char _op;
    func_t _call_back_function;

public:
    CalculateTask(){};
    CalculateTask(int num1, int num2, char op, func_t call_back_function)
        : _num1(num1)
        , _num2(num2)
        , _op(op)
        , _call_back_function(call_back_function)
    {}

public:
    string operator()() {
        int result = _call_back_function(_num1, _num2, _op);
        char buffer[1024];
        snprintf(buffer, sizeof(buffer), "%d %c %d = %d", _num1, _op, _num2, result);

        return string(buffer);
    }

    string showTask() {
        char buffer[1024];
        snprintf(buffer, sizeof buffer, "%d %c %d = ?", _num1, _op, _num2);

        return string(buffer);
    }
};

int calculate(int num1, int num2, char op) {
    int result = 0;

    switch (op) {
    case '+':
        result = num1 + num2;
    break;
    case '-':
        result = num1 - num2;
    break;
    case '*':
        result = num1 * num2;
    break;
    case '/': {
        if (num2 == 0) {
            cerr << "div zero err!" << endl;
            result = -1;  
        }
        else {
            result = num1 / num2;
        }
    }
    break;
    case '%': {
        if (num2 == 0) {
            cerr << "mod zero err!" << endl;
            result = -1;  
        }
        else {
            result = num1 % num2;
        }
    }
    break;
    default:
        cerr << "no this operator!" << endl;
    break;
    }

    return result;
}

class SaveTask {
private:
    using func_t = function<void(const string&)>;

private:
    string _message;
    func_t _function;

public:
    SaveTask() = default;
    SaveTask(const string& message, func_t function)
        : _message(message)
        , _function(function)
    {}

public:
    void operator()() {
        _function(_message);
    }
};

void save(const string& message) {
    FILE* fp = (FILE*)fopen(save_file, "a+");
    assert(fp);

    fputs(message.c_str(), fp);
    fputs("\n", fp);

    fclose(fp);
}